package ca.cbc.gisdigester.digester;

import ca.cbc.giscommon.entity.Content;
import ca.cbc.giscommon.entity.Source;
import ca.cbc.giscommon.util.GISConfig;
import ca.cbc.giscommon.util.GeometryUtil;
import ca.cbc.gisdigester.Main;
import ca.cbc.gisdigester.geoparser.GeoRSSModule;
import ca.cbc.gisdigester.geoparser.GeoRSSUtils;

import com.sun.syndication.feed.synd.SyndEntry;
import com.sun.syndication.feed.synd.SyndFeed;
import com.sun.syndication.io.FeedException;
import com.sun.syndication.io.SyndFeedInput;
import com.sun.syndication.io.XmlReader;
import com.vividsolutions.jts.geom.Geometry;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

public enum FeedContentDigester {
    instance;
    private Logger logger = LoggerFactory.getLogger(FeedContentDigester.class);

    /**
     * @param sourceLink -- a url string or a file name string
     */
    @SuppressWarnings("unchecked")
    public List<Content> digest(Source source) {
        logger.info("##Digesting 3rd party feed with source {}", source);
        List<Content> contents = new ArrayList<Content>();
        String sourceLink = source.getLink();
        Geometry defaultTheGeom = source.getDefaultGeom();
        SyndFeed feed;
        try {
            if (sourceLink.startsWith("http")) {    //input is a url
            	URLConnection connection = (new URL(sourceLink)).openConnection();
            	GISConfig.instance.changeConnectionTimeouts(connection);
            	
                
                feed = new SyndFeedInput().build(getReaderFromConnection(connection));
            } else {                            //input is a file
                feed = new SyndFeedInput().build(new File(sourceLink));
            }
            
            List<SyndEntry> entries = feed.getEntries();
            for (SyndEntry entry : entries) {
                //get pubDate
                Date pubDate = (entry.getPublishedDate() == null) ? feed.getPublishedDate() : entry.getPublishedDate();
                if (pubDate == null) {
                    logger.error("Must provide a pubDate when digesting!");
                    continue;
                }

                //get theGeom
                GeoRSSModule geoRSSModule = GeoRSSUtils.getGeoRSS(entry);
                Geometry theGeom = (geoRSSModule == null) ? defaultTheGeom :
                        GeometryUtil.instance.parsePoint(geoRSSModule.getLongitude(), geoRSSModule.getLatitude());

                String description = (entry.getDescription() != null) ? entry.getDescription().getValue() : null;
                Content content = new Content(entry.getTitle(), entry.getLink(), entry.getAuthor(), description,
                        pubDate.getTime(), theGeom, source);

                //logger.debug("---Digested feed content is {}", content);
                contents.add(content);
            }

        } catch (IllegalArgumentException e) {
            logger.error("Error when parsing url/file {}.", sourceLink, e);
        } catch (MalformedURLException e) {
            logger.error("Error when parsing url/file {}.", sourceLink, e);
        } catch (FeedException e) {
            logger.error("Error when parsing url/file {}.", sourceLink, e);
        } catch (IOException e) {
            logger.error("Error when parsing url/file {}.", sourceLink, e);
        }

        logger.info("##3rd party feed with source {} digested.", sourceLink);
        return contents;
    }
    /**
     * 
     * @param connection
     * @return
     */
    private Reader getReaderFromConnection(URLConnection connection) throws IOException{
    		BufferedInputStream bis = new BufferedInputStream(connection.getInputStream());
		 	int bytesRead = 0;
		 	byte[] buffer = new byte[1024];
		 	StringBuffer strBuf = new StringBuffer();
       
        while ((bytesRead = bis.read(buffer)) != -1) {
            String chunk = new String(buffer, 0, bytesRead);
            strBuf.append(chunk);
        }
        return new StringReader(strBuf.toString());
    }
}
